package com.jf.docsify.interceptor;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;

import com.jf.docsify.common.annotation.NotAuth;
import com.jf.docsify.common.exception.DocsifyException;
import com.jf.docsify.common.utils.AssertUtil;
import com.jf.docsify.common.utils.TokenUtil;
import com.jf.docsify.common.utils.WebUtil;
import com.jf.docsify.modules.model.SysUser;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;

/**
 * Description: 认证拦截器
 *
 * @author chenwr
 * @version 1.0
 *
 * <pre>
 * 修改记录:
 * 修改后版本           修改人       修改日期         修改内容
 * 2022/7/26.1       chenwr    2022/7/26           Create
 * </pre>
 * @date 2022/7/26
 */
public class AuthInterceptor implements Interceptor {

    public static final String JWT_KEY = "Authorization";

    @Override
    public void intercept(Invocation invocation) {
        Controller controller = invocation.getController();
        boolean notAuthMethod = invocation.getMethod().isAnnotationPresent(NotAuth.class);
        boolean notAuthCtrl = controller.getClass().isAnnotationPresent(NotAuth.class);
        if (notAuthMethod) {
            invocation.invoke();
            return;
        } else if (notAuthCtrl) {
            invocation.invoke();
            return;
        }

        String jwtVal = getJwtVal(controller);
        HttpServletRequest request = controller.getRequest();
        String ipAddr = WebUtil.getIpAddr(request);
        AssertUtil.hasText(jwtVal, "token 不能为空");
        SysUser user = TokenUtil.getUser(jwtVal);
        try {
            AssertUtil.notNull(user, "token 已失效");
        } catch (Exception e) {
            String actionKey = invocation.getActionKey();
            if (actionKey.startsWith("/admin/logout")) {
                invocation.invoke();
                return;
            }
            DocsifyException.throwE(e);
        }
        boolean validateToken = TokenUtil.validateToken(String.valueOf(user.getId()), jwtVal);
        AssertUtil.isTrue(validateToken, "token 已失效");
        AssertUtil.isTrue(ipAddr.equals(user.getLoginIp()), "token 已失效");
        controller.setAttr("user", user);
        invocation.invoke();
        controller.removeAttr("user");
    }

    private String getJwtVal(Controller controller) {
        String jwtVal = controller.getHeader(JWT_KEY);
        jwtVal = StringUtils.defaultIfBlank(jwtVal, controller.getCookie(JWT_KEY));
        jwtVal = StringUtils.defaultIfBlank(jwtVal, controller.getSessionAttr(JWT_KEY));
        jwtVal = StringUtils.defaultIfBlank(jwtVal, controller.getPara(JWT_KEY));
        jwtVal = StringUtils.defaultIfBlank(jwtVal, controller.getAttr(JWT_KEY));
        if (StringUtils.isNotBlank(jwtVal)) {
            jwtVal = jwtVal.replaceFirst("Bearer ", "").trim();
        }
        return jwtVal;
    }
}